home *** CD-ROM | disk | FTP | other *** search
/ Info-Mac 4 / Info_Mac IV CD-ROM (Pacific HiTech Inc.)(August 1994).iso / Development / Source / MovieToolBox / pictmovier.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-09  |  18.7 KB  |  678 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        PictMovier.c
  3.  
  4.     Contains:    Application to make a movie from PICTs with various processes
  5.     
  6.     Written by:    Mark Krueger
  7.     Copyright:    © 1990-1991 by Apple Computer, Inc., all rights reserved.
  8.  
  9.         This example shows how you can make movies by doing processing on pictures.
  10.     
  11.     This allows a process that takes a long time to be shown at much faster rates
  12.     as a QuickTime movie. Any type of processing can be done, such as filtering, 
  13.     transitions, 3-D transformations. This example shows two trivial examples.
  14.     
  15.     The first simple does a linear cross fade between two images. The second creates
  16.     a random dot stereogram ( an image that if you stare at it long enough you can
  17.     see three dimensional depth in ( without special glasses ). This works from a single
  18.     image and shows how the effect can be varied from frame to frame.
  19.     
  20.     Note that the code is not necessarily well commented, but should prove useful as 
  21.     a jumping off point for making your own movie creation applications.
  22.     
  23.     Change History:
  24.     Friday, June 5, 1992 3:27:34 PM    MHK    New Today
  25.     Nov. 16th, 1993    RMF - Merged into this program ImportExportMovie.c example, 
  26.                           and added options for selecting effect for PiictMovier.c and show preview
  27.     Jan  17th, 194    RMF - Added option to append movie to existing movie (see DoMovie()).
  28.     Feb 9th,1994    RMF    - Fix up DoStage for new Menu structure (eg. Direction menu, Effect Menu).
  29.                         - Added BackGround Color option on Slide
  30.       
  31. */
  32.  
  33. #include "gGlobals.h"
  34.  
  35. #include    <pascal.h>
  36. #include    <Scrap.h>
  37. #include    <Desk.h>
  38. #include    <string.h>
  39. #include    <stdio.h>
  40. #include    <Fonts.h>
  41. #include    <Math.h>
  42.  
  43.     
  44. void DoRoll(long stageNum,long totalStages, int direction, int rollfill);
  45. CWindowPtr    MakeSWindow(Rect *frame,StringPtr name,GWorldPtr buffer);
  46.  
  47. /*
  48.     Close a window
  49.     
  50. */
  51. DoClose(WindowPtr wind)
  52. {
  53.     if ( wind == nil)    return(0);
  54.     
  55.     if ( gActiveWindow == wind )    gActiveWindow = nil;
  56.         
  57.     if ( wind == (WindowPtr)gSrcWindow ) {        /* Primary source image */
  58.         DoClear();
  59.         gSrcWindow = nil;
  60.         DisposeGWorld(gWorld);
  61.         gWorld = nil;
  62.     } else
  63.     if ( wind == (WindowPtr)gAltWindow ) {         /* Sec. source image */
  64.         DoClear();
  65.         gAltWindow = nil;
  66.         DisposeGWorld(gAltWorld);
  67.         gAltWorld = nil;
  68.     } else
  69.     
  70.     if ( wind == (WindowPtr)gDstWindow ) {         /* Preview image or Build Image window */
  71.         gDstWindow = nil;
  72.         }
  73.     CloseWindow(wind);
  74.     return(0);
  75. }
  76.  
  77.  
  78.  
  79. void DoStage(long stageNum,long totalStages,Boolean reverse)
  80. {
  81.     switch ( gEffectType ) {
  82.     
  83.     case EFFECT_CrossFad:    DoCrossFade(stageNum,totalStages,reverse);
  84.         break;
  85.         
  86.     case EFFECT_Roll:
  87.     case EFFECT_Slide:
  88.         if (reverse) stageNum = totalStages - stageNum;        /* Reverse effect */
  89.         
  90.         DoRoll(stageNum,totalStages, gEffectDirection - EFFECT_Roll_Left + 1, (EFFECT_Roll == gEffectType));
  91.         break;
  92.     case EFFECT_StereoGram:    DoRandomDotStereogram(stageNum,totalStages,reverse);
  93.         break;
  94.     case Effect_AdobeWipe:
  95.         break;
  96.         }
  97. }
  98.  
  99. /*********************************************
  100.  
  101.     This processing routine creates a random dot stereogram of the input picture.
  102.     The second picture is not used.
  103.     
  104.     
  105. ********************************************/
  106. static Boolean         gDepthDecodeTabInted = false;
  107. static short        gDepthFactor = 16;
  108.  
  109. void DoRandomDotStereogram(long stageNum,long totalStages,Boolean reverse)
  110. {
  111.     /* StdFile stuff */
  112.     short            gStripWidth = 128;
  113.  
  114.     CGrafPtr    savePort;
  115.     GDHandle    saveGD;
  116.     char         *ip,*rp,*pp,*opp,*qp;
  117.     char         *sip,*srp,*spp;
  118.     short        rowBytes;
  119.     short        sRowBytes;
  120.     char        mode = 1;
  121.     
  122.     /* for sepecifying compression */
  123.     
  124.     short        i,j,x,y,height,width;
  125.     unsigned char pix,spix,ppix,qpix;
  126.  
  127.     char        *lineBuf = nil;
  128.     char        *newLineBuf = nil;
  129.     char        *tLineBuf = nil;
  130.     unsigned long timeseed;
  131.  
  132. #define    RDS_DEPTH_FACTOR_VARIES            // set this to increase depth as movie progresses
  133.  
  134. #define    RDS_STRIP_WIDTH_VARIES            // set this to increase repeat strip as movie progresses
  135.  
  136. // #define    RDS_NEW_SEED_EACH_FRAME            // set this to have a new random background for each frame 
  137.  
  138. #ifdef    RDS_NEW_SEED_EACH_FRAME
  139.     GetDateTime(×eed);
  140.     rand(time);
  141. #else
  142.     rand(1);
  143. #endif
  144.  
  145. #ifdef    RDS_DEPTH_FACTOR_VARIES
  146.     gDepthFactor = 1 + (stageNum * 64) / totalStages;
  147.     gDepthDecodeTabInted = false;
  148. #else
  149.     gDepthFactor = 16;
  150. #endif
  151.  
  152. #ifdef    RDS_STRIP_WIDTH_VARIES
  153.     gStripWidth = 32 + (stageNum * 256) / totalStages;
  154. #else
  155.     gStripWidth = 128;
  156. #endif
  157.  
  158.     GetGWorld(&savePort,&saveGD);
  159.      SetGWorld(gDstWorld,nil);
  160.     EraseRect(&gDstWorld->portRect);
  161.     
  162.     width = gWorld->portRect.right - gWorld->portRect.left;
  163.     height = gWorld->portRect.bottom - gWorld->portRect.top;
  164.     LockPixels(gWorld->portPixMap);
  165.     sRowBytes  = (*gWorld->portPixMap)->rowBytes & 0x7fff;
  166.     sip  = GetPixBaseAddr(gWorld->portPixMap);
  167.     SetGWorld(gDstWorld,nil);
  168.     
  169.     LockPixels(gDstWorld->portPixMap);
  170.     rowBytes = (*gDstWorld->portPixMap)->rowBytes & 0x7fff;
  171.     ip = GetPixBaseAddr(gDstWorld->portPixMap);
  172.  
  173.     lineBuf = NewPtr(sRowBytes);
  174.     if ( lineBuf == nil ) {
  175.         Error("allocating line buffer",0);    goto done;
  176.         }
  177.     newLineBuf = NewPtr(rowBytes);
  178.     if ( newLineBuf == nil ) {
  179.         Error("allocating nline buffer",0);    goto done;
  180.         }
  181.     tLineBuf = NewPtr(sRowBytes);
  182.     if ( tLineBuf == nil ) {
  183.         Error("allocating tline buffer",0);    goto done;
  184.         }
  185.         
  186.     SwapMMUMode(&mode);
  187.     if ( gStandardP.depth == 1 ) {
  188.     
  189.         rp = ip;
  190.         for(y=0; y<height; y++) {
  191.             pp = rp;
  192.             for(x=0;x<gStripWidth/8;x++,pp++)  {
  193.                 pix = 0;
  194.                 for ( i=0; i < 8; i++ ) { 
  195.                     pix <<= 1;
  196.                     if ( rand(0) % 5 == 0 )
  197.                         pix |= 1;
  198.                 }
  199.                 qp = pp;
  200.                 for ( j=0; j < width/gStripWidth; j++ ) {
  201.                     *qp = pix;
  202.                     qp += gStripWidth /8;
  203.                 }
  204.             }
  205.             rp += rowBytes;
  206.         }
  207.         rp = ip;
  208.         srp = sip;
  209.     
  210.     
  211.         for(y=0;y<height;y++) {
  212.             pp = rp;
  213.             spp = srp;
  214.             spp += gDepthFactor/8;
  215.             qp = pp;
  216.             BlockMove(pp,tLineBuf,sRowBytes);
  217.             qp = tLineBuf;
  218.             pp = qp;
  219.             qp += gDepthFactor/8;
  220.             
  221.             opp = newLineBuf;
  222.             for(x=0;x < width/8-gStripWidth/8;x++ ,pp++,qp++,opp++) {
  223.                 spix = *spp++;
  224.                 qpix = *qp;
  225.                 ppix = *pp;
  226.                 pix = 0;
  227.                 for ( i=0; i < 8; i++ ) { 
  228.                     pix <<= 1;
  229.                     if ( (spix & 0x80 ) )
  230.                         pix |= (qpix & 0x80) != 0 ? 1 : 0;
  231.                     else
  232.                         pix |= (ppix & 0x80) != 0 ? 1 : 0;
  233.                     spix <<= 1;
  234.                     ppix <<= 1;
  235.                     qpix <<= 1;
  236.                 }
  237.                 *opp = pix;
  238.                 *(pp+gStripWidth/8) = pix;
  239.             }
  240.             BlockMove(newLineBuf,rp+gStripWidth/8,rowBytes-gStripWidth/8);
  241.             rp += rowBytes;
  242.             srp += sRowBytes;
  243.         }
  244.     } else
  245.     
  246.     if ( gStandardP.depth == 8 || gStandardP.depth == 40 ) {
  247.     
  248.         rp = ip;
  249.  
  250.         for(y=0; y<height; y++) {
  251.             pp = rp;
  252.             for(x=0;x<gStripWidth;x++)  {
  253.                 *pp++ = rand(0);
  254.             }
  255.             rp += rowBytes;
  256.         }
  257.  
  258.         rp = ip;
  259.         srp = sip;    
  260.  
  261.         for(y=0;y<height;y++) {
  262.             pp = rp;
  263.             spp = srp;
  264.             spp += gStripWidth;
  265.     
  266.             qp = pp;
  267.             BlockMove(pp,tLineBuf,sRowBytes);
  268.             qp = tLineBuf;
  269.             pp = qp;
  270.             
  271.             opp = newLineBuf;
  272.             for(x=0;x < width-gStripWidth;x++ ,pp++,qp++,opp++) {
  273.                 spix = *spp++;
  274.                 ppix = *pp;
  275.                 
  276.                 pix = *(qp + DecodeDepth(spix));
  277.                 *opp = pix;
  278.                 *(pp+gStripWidth) = pix;
  279.             }
  280.             BlockMove(newLineBuf,rp+gStripWidth,rowBytes-gStripWidth);
  281.             rp += rowBytes;
  282.             srp += sRowBytes;
  283.         }
  284.     }
  285.     SwapMMUMode(&mode);
  286.      UnlockPixels(gDstWorld->portPixMap);
  287.  
  288.     SetGWorld(savePort,saveGD);
  289. done:
  290.     if ( newLineBuf )    DisposPtr(newLineBuf);
  291.     if ( lineBuf )        DisposPtr(lineBuf);
  292.     if ( tLineBuf )        DisposPtr(tLineBuf);
  293. }
  294.  
  295. /*********************************************
  296.  
  297.      a better random function than the one in the ROM 
  298.      
  299. *********************************************/
  300.  
  301. long rand(long reseed)
  302. {
  303. #define    A    16807
  304. #define    M    2147483647
  305. #define    Q    127773
  306. #define    R    2836
  307.     static long seed = 1;
  308.     long lo,hi,test;
  309.     
  310.     if ( reseed != 0 )    seed = reseed;
  311.     hi = seed / Q;
  312.     lo = seed % Q;
  313.     test = A*lo - R*hi;
  314.     if ( test > 0 )    seed = test;
  315.     else            seed = test + M;
  316.     return ( seed/(M>>16));
  317. }
  318.  
  319. unsigned char DecodeDepth(unsigned char pix)
  320. {    static unsigned char table[256];
  321.     short i;
  322.     
  323.     if ( !gDepthDecodeTabInted ) {
  324.         gDepthDecodeTabInted = 1;
  325.         for ( i=0; i < 255; i++ ) {
  326.             table[i] = (i * gDepthFactor)/255;
  327.         }
  328.     }
  329.     return(table[pix]);
  330. }
  331.  
  332. /*********************************************
  333.  
  334.     This processing routine does a linear cross dissolve between the two images,
  335.     using CopyBits with blend mode. It shows how to do a process which involves 
  336.     both images. Any type of process could be done here, using the three parameters
  337.     to determine how much of the processing has progressed.
  338.     
  339.     Note: See the Develop article by Konstantin Othmar ( sorry I forget the issue number )
  340.     about CopyBits to learn how to do other cool effects just using CopyBits.
  341.     
  342. *********************************************/
  343.  
  344. void DoCrossFade(long stageNum,long totalStages,Boolean reverse)
  345. {
  346.     GWorldPtr    saveWorld;
  347.     GDHandle    saveGD;
  348.     RGBColor     opColor;
  349.     
  350.     
  351.     if ( reverse )
  352.         opColor.red  = opColor.green  = opColor.blue  = (stageNum*0xffff)/totalStages;
  353.     else
  354.         opColor.red  = opColor.green  = opColor.blue  = ((totalStages-stageNum)*0xffff)/totalStages;
  355.     
  356.     GetGWorld(&saveWorld,&saveGD);
  357.  
  358.     SetGWorld(gDstWorld,nil);
  359.     CopyBits((BitMap *)*gAltWorld->portPixMap,(BitMap *)*gDstWorld->portPixMap,
  360.                 &gAltWorld->portRect,&gDstWorld->portRect,ditherCopy,nil);
  361.     OpColor(&opColor);
  362.     CopyBits((BitMap *)*gWorld->portPixMap,(BitMap *)*gDstWorld->portPixMap,
  363.                 &gWorld->portRect,&gDstWorld->portRect,blend,nil);
  364.     SetGWorld(saveWorld,saveGD);
  365.     
  366. }    /* End of () */
  367.  
  368. /*********************************************
  369.  
  370.     Create the movie by processing all the frames.
  371.     
  372. ********************************************/
  373. OSErr OpenCreateMovie(Boolean Append, Movie *gMovie, short *resRefNum, short *resID, SFReply *sfr)
  374. {    OSErr result;
  375.     FSSpec        mySpec;                            /* Data structure with filename, etc. */
  376.     
  377.     ClearMoviesStickyError();                    /* Clear any old errors */
  378.     result = FSMakeFSSpec(sfr->vRefNum, 0, (unsigned char *) sfr->fName, &mySpec);
  379.     if (result == fnfErr) result = 0;
  380.     
  381.     if (Append)     {        /* RMF */
  382.         //    Open a movie file using the FSSpec and create a movie from that file.
  383.         
  384.         result = OpenMovieFile(&mySpec, resRefNum, fsRdWrPerm);
  385.         if (result == noErr) {
  386.             result = NewMovieFromFile(gMovie,*resRefNum, resID, nil,newMovieActive, nil);
  387.             }
  388.     } else
  389.         result = CreateMovieFile(  &mySpec, 'TVOD',0,createMovieFileDeleteCurFile, resRefNum, gMovie);
  390.     return result;
  391. }    /* End of () */
  392.  
  393. CWindowPtr OpenReplaceMovieWindow(StringPtr name, short width, short height)
  394. {    Rect        rect;
  395.     if ( gDstWindow ) {
  396.         CloseWindow((WindowPtr)gDstWindow);
  397.         gDstWindow = nil;
  398.         }    
  399.     SetRect(&rect,80,80, width+80, height+80);
  400.     gDstWindow = MakeSWindow(&rect, name, nil);
  401.  
  402.     return gDstWindow;
  403. }    /* End of () */
  404.  
  405. OSErr DoMovie(Boolean Append)
  406. {    GWorldPtr    saveWorld;
  407.     GDHandle    saveGD;
  408.     short         resRefNum, resID = 0;
  409.     OSErr        result;
  410.  
  411.     /* Stuff for creating the file */
  412.  
  413.     SFReply        sfr;                            /* StdFile reply */
  414.     Movie        gMovie = 0;                            /* Our movie, track and media */
  415.     Track        gTrack, gTackOld;
  416.     Media        gMedia;
  417.     long         maxCompressedFrameSize;            /* Max size of compressed frame        */
  418.     long        compressedFrameSize;            /* Size of current compressed frame */
  419.     Handle        compressedFrameBitsH = nil;        /* Buffer for the compressed data    */
  420.     ImageDescription    **imageDescriptionH = nil;        /* Contains info about the sample    */
  421.     Ptr            data;
  422.     EventRecord myEvent;
  423.     ImageSequence    seq;
  424.     Rect        dstRect;
  425.     short        i, width,height;
  426.     
  427.     TimeValue     MyMediaDuration, timeLength, sampleDuration;
  428.     Boolean     foundVideo;
  429.     
  430.     GetGWorld(&saveWorld,&saveGD);
  431.     if ( !gDstWorld || !gWorld || !gAltWorld) {        /* No offscreen image to make movie from, */
  432.         SysBeep(0);    return;                            /* no drawing area to image movie */
  433.         }
  434.         
  435.     /* Prompt the user for a file name and create it */
  436.     if (Append) {                /* RMF */
  437.         Point        where;
  438.         SFTypeList    typeList;
  439.         //---------------------------------------------------------------------------------------------
  440.         //    Ask for a source movie file using Standard Preview.
  441.         //    Use (-2,-2) to center on the best device.
  442.         //---------------------------------------------------------------------------------------------
  443.     
  444.         where.h = where.v = -2;
  445.         typeList[0] = 'MooV';
  446.         SFGetFilePreview(where,"\p", nil,1,typeList,nil, &sfr);
  447.     
  448.     } else {
  449.         static Str255    name = "\pMovieToolBox Movie";
  450.         Point        where;
  451.         where.h = where.v = -2;
  452.         SFPutFile(where, (StringPtr) "\pMovie file to create:",(StringPtr)name,nil,&sfr);
  453.         if (sfr.good) 
  454.             BlockMove(sfr.fName,name,sfr.fName[0]+1);
  455.         }
  456.     if (!sfr.good)    return;
  457.     
  458.     
  459.     width = gOriginalPicFrame.right - gOriginalPicFrame.left;
  460.     height = gOriginalPicFrame.bottom - gOriginalPicFrame.top;
  461.     if ( gOversample ) {
  462.         width /= 2;
  463.         height /= 2;
  464.         }
  465.         
  466.     if (OpenReplaceMovieWindow(sfr.fName, width, height) == nil) goto done;        /* Error opening window */
  467.         
  468.     imageDescriptionH = (ImageDescription **)NewHandle( sizeof( ImageDescription));    /* handle for image descriptor */
  469.     if ( imageDescriptionH == nil ) {
  470.         Error("Out of Memory",MemError());
  471.         goto done;
  472.     }
  473.     
  474.     result = OpenCreateMovie(Append, &gMovie, &resRefNum, &resID, &sfr);
  475.  
  476.     if (result == noErr) result = GetMoviesError();    
  477.     if (result != noErr) {
  478.         Error("Opening Movie file", result);    goto done;
  479.         }
  480.     
  481.             
  482.     /*    Find a movie's video track.    */
  483. // RMF
  484.     foundVideo = false;
  485.     for (i=1; ((i<=GetMovieTrackCount(gMovie)) && (!foundVideo)); i++) {
  486.         OSType                    myMediaType;
  487.         
  488.         gTrack = GetMovieIndTrack(gMovie, i);
  489.         gMedia = GetTrackMedia(gTrack);
  490.         GetMediaHandlerDescription(gMedia, &myMediaType, nil, nil);
  491.         if (myMediaType == VideoMediaType)
  492.             foundVideo = true;
  493.         }    /* End for() */
  494. // RMF
  495.     if (foundVideo == true)    {    
  496.         timeLength = GetMediaDuration(gMedia);    
  497.     } else {
  498.         timeLength = 0L;
  499.         
  500.         gTrack = NewMovieTrack(gMovie,(long)width<<16, (long)height<<16, 0 /* volume */);
  501.         gMedia = NewTrackMedia(gTrack, VideoMediaType, gStandardP.frameRate>>16L, nil,(OSType) nil);
  502.     //    SetMediaTimeScale(gMedia, 1);
  503.         }
  504.         
  505.     BeginMediaEdits( gMedia );                                        /* adding samples to the media */
  506.     GetMaxCompressionSize(gAltWorld->portPixMap,&gAltWorld->portRect,
  507.                         gStandardP.depth,gStandardP.spatialQuality,
  508.                         gStandardP.theCodecType,gStandardP.theCodec,&maxCompressedFrameSize);    
  509.  
  510.     compressedFrameBitsH = NewHandle(maxCompressedFrameSize);    
  511.     if ( compressedFrameBitsH == nil ) {
  512.         Error("Out of Memory",MemError());    goto bail;
  513.         }
  514.         
  515.     GetGWorld(&saveWorld,&saveGD);                
  516.     SetGWorld((CGrafPtr)gDstWorld,nil);    PaintRect(&gDstWorld->portRect);
  517.     
  518.     if ( (result=CompressSequenceBegin(&seq,gDstWorld->portPixMap,nil,
  519.             &gDstWorld->portRect,nil,gStandardP.depth,gStandardP.theCodecType, 
  520.             gStandardP.theCodec,
  521.             gStandardP.spatialQuality,gStandardP.temporalQuality,gStandardP.keyFrameRate,
  522.             nil,codecFlagUpdatePreviousComp,imageDescriptionH)) != 0 ) {
  523.         Error("CompressSequenceBegin Failed. #",result);
  524.         goto bail2;
  525.         }
  526.         
  527.     SetGWorld(saveWorld,saveGD);
  528.     while ( WaitNextEvent( everyEvent, &myEvent, 0, nil) != 0 ) {
  529.         if ( HandleEvents(&myEvent) )     goto bail2;        /* RMF - was return; */
  530.         }
  531.     
  532.     
  533.     SetRect(&dstRect, 0,0, gOriginalPicFrame.right/2, gOriginalPicFrame.bottom/2);
  534.     i = GetMediaTimeScale(gMedia);    /*    durationPerSample    */
  535.     i = 1;
  536.     for ( gFrameNumber=0; gFrameNumber < gNumberSteps; gFrameNumber++ ) {
  537.         SetGWorld(saveWorld,saveGD);
  538.         if ( WaitNextEvent( everyEvent, &myEvent, 0, nil) != 0 ) {        /* Do background events... */
  539.             if ( HandleEvents(&myEvent) )    break;
  540.             }
  541.             
  542.         SetGWorld((CGrafPtr)gDstWorld,nil);
  543.         PaintRect(&gDstWorld->portRect);
  544.  
  545.         /* assumes: gDstWorld, gWorld && gAltWorld are valid, 
  546.                     Draw the current stage in the buffer */
  547.         DoStage(gFrameNumber, gNumberSteps, gReverse);
  548.  
  549.         SetGWorld((CGrafPtr)gDstWindow,nil);
  550.         InvalRect(&gDstWindow->portRect);
  551.         DoHLock(compressedFrameBitsH);
  552.         data = StripAddress(*compressedFrameBitsH);
  553.         
  554.         if ( gOversample )  {            /* use: gBufferWorld to create oversame image */
  555.             SetGWorld(gBufferWorld,nil);
  556.             CopyBits((BitMap *)*gDstWorld->portPixMap,(BitMap *)*gBufferWorld->portPixMap,
  557.                 &gDstWorld->portRect,&dstRect,ditherCopy,nil);
  558.         
  559.             result = CompressSequenceFrame(seq,gBufferWorld->portPixMap,&dstRect,
  560.                     codecFlagUpdatePreviousComp,data,&compressedFrameSize,nil,nil);
  561.         } else {
  562.             SetGWorld((CGrafPtr)gDstWorld,nil);
  563.             result = CompressSequenceFrame(seq,gDstWorld->portPixMap,&gDstWorld->portRect,
  564.                     codecFlagUpdatePreviousComp,data,&compressedFrameSize,nil,nil);
  565.             }
  566.             
  567.         if ( result ) {
  568.             Error("Compress Sequence Frame Failed. #",result);
  569.             break;
  570.             }
  571.             
  572.         DoHUnlock(compressedFrameBitsH);
  573.         
  574.         result = AddMediaSample(gMedia,
  575.                     compressedFrameBitsH, 0L,compressedFrameSize,
  576.                     (TimeValue) i,            /*    durationPerSample    */
  577.                     (SampleDescriptionHandle) imageDescriptionH,
  578.                     1L,    /* numberOfSamples */
  579.                     0,     /* sampleFlags */
  580.                     &sampleDuration);
  581.         if ( result ) {
  582.             Error("AddMediaSample Failed. #",result); break;
  583.             }
  584.             
  585.     }    /* End for() */
  586. bail2:
  587.     CDSequenceEnd(seq);
  588.     
  589. bail:
  590. {    TimeValue     test;
  591.  
  592.     MyMediaDuration = GetMediaDuration(gMedia);
  593.     test = -1;
  594.     result = InsertMediaIntoTrack(gTrack,
  595.                                     test,                /* -1 = at end, 0L = at start of Track */
  596.                                     timeLength,                        /* Media time */
  597.                                     MyMediaDuration - timeLength,    /* amount of data to insert */
  598.                                     1<<16);                            /* Media Rate */
  599.     if ( result ) {
  600.         Error("InsertMediaIntoTrack Failed. #",result);
  601.         }
  602.         
  603.     if (Append) {    
  604.         result = UpdateMovieResource(gMovie, resRefNum, resID, nil);
  605.     } else
  606.         result = AddMovieResource(gMovie, resRefNum, &resID, nil);
  607.     if ( result ) {
  608.         Error("AddMovieResource Failed. #",result);
  609.         }
  610.     EndMediaEdits( gMedia );                /* We're done adding samples */
  611.     }
  612.     
  613. //    MakeFilePreview(resRefNum, (ProgressProcRecordPtr)-1L);        /* RMF */
  614.     
  615.     CloseMovieFile( resRefNum );
  616.  
  617. done: 
  618.     SetGWorld(saveWorld,saveGD);
  619.     if ( imageDescriptionH )    DoDisposHandle((Handle)imageDescriptionH);
  620.     if ( compressedFrameBitsH )    DoDisposHandle((Handle)compressedFrameBitsH);
  621.     if ( gMovie )                DisposeMovie(gMovie);    
  622.     gMovie = nil;
  623.     
  624.     if ( gDstWindow ) { 
  625.         CloseWindow((WindowPtr)gDstWindow);    gDstWindow  = nil;
  626.         }
  627.     SetGWorld(saveWorld,saveGD);
  628. }    /* End of DoMovie() */
  629.  
  630.  
  631.  
  632.  
  633.  
  634. /********************************************
  635.  
  636.     Update a window
  637.     
  638. ********************************************/
  639. void DoUpdate(CWindowPtr wind)
  640. {    GWorldPtr    saveWorld,gw;
  641.     GDHandle    saveGD;
  642.     char        c[32];
  643.     
  644.     GetGWorld(&saveWorld,&saveGD);
  645.     if ( wind == gDstWindow ) {
  646.         BeginUpdate((WindowPtr)wind);
  647.         SetGWorld((CGrafPtr)wind,nil);
  648.         CopyBits((BitMap *)*gDstWorld->portPixMap,(BitMap *)*wind->portPixMap,
  649.                 &gDstWorld->portRect,&wind->portRect,ditherCopy,nil);
  650.                 
  651.         if ( gFrameNumber >= 0 ) {    /* Active building move ... label current frame */
  652.             MoveTo(20,20);
  653.             TextSize(12);    TextFace(bold);    TextMode(patBic);
  654.             NumToString(gFrameNumber+1,(StringPtr)&c);    DrawString((StringPtr)&c);    
  655.             DrawString((StringPtr)"\p/");
  656.             NumToString(gNumberSteps,(StringPtr)&c);    DrawString((StringPtr)&c);
  657.             
  658.             MoveTo(21,21);    TextMode(srcOr);
  659.             NumToString(gFrameNumber+1,(StringPtr)&c);    DrawString((StringPtr)&c);
  660.             DrawString((StringPtr)"\p/");
  661.             NumToString(gNumberSteps,(StringPtr)&c);    DrawString((StringPtr)&c);
  662.             }
  663.         EndUpdate((WindowPtr)wind);
  664.         SetGWorld(saveWorld,saveGD);
  665.         return;
  666.         }
  667.         
  668.     SetGWorld(wind,nil);
  669.     gw = (GWorldPtr)GetWRefCon((WindowPtr)wind);        /* Offscreen GWorldPtr store in WRefCon */
  670.     BeginUpdate((WindowPtr)wind);
  671.     CopyBits((BitMap *)*gw->portPixMap,(BitMap *)*wind->portPixMap,
  672.             &gw->portRect,&wind->portRect,ditherCopy,nil);
  673.     EndUpdate((WindowPtr)wind);
  674.     SetGWorld(saveWorld,saveGD);
  675. }    /* End of () */
  676.  
  677.  
  678.